home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 79 / maccd 79.iso / multimedial / GL Tron / Source / gltron / sound3d.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-07-20  |  5.5 KB  |  229 lines  |  [TEXT/CWIE]

  1. #include "gltron.h"
  2.  
  3. //#define memcpy(from,to,size) BlockMoveData(to,from,size)
  4.  
  5. typedef struct {
  6.   float x, y;
  7. } Point;
  8.  
  9. #define USOUND 500
  10. void getSound3dData(int i_player, int i_object, 
  11.            float *pan, float *vol, float *shift) {
  12.   Point vp, vo, lc, pc, pp, po;
  13.   Player *player, *object;
  14.  
  15.   float cos2phi;
  16.   float dist2;
  17.   float scalar;
  18.   
  19.   player = &(game->player[ i_player ]);
  20.   object = &(game->player[ i_object ]);
  21.   
  22.   pp.x = player->data->posx;
  23.   pp.y = player->data->posy;
  24.  
  25.   vp.x = game->settings->game_speed * dirsX[ player->data->dir ];
  26.   vp.y = game->settings->game_speed * dirsY[ player->data->dir ];
  27.  
  28.   lc.x = player->camera->target[0] - player->camera->cam[0];
  29.   lc.y = player->camera->target[1] - player->camera->cam[1];
  30.  
  31.   pc.x = player->camera->cam[0];
  32.   pc.y = player->camera->cam[1];
  33.  
  34.   po.x = object->data->posx;
  35.   po.y = object->data->posy;
  36.  
  37.   vo.x = game->settings->game_speed * dirsX[ object->data->dir ];
  38.   vo.y = game->settings->game_speed * dirsY[ object->data->dir ];
  39.  
  40.   scalar = lc.x * ( po.x - pp.x ) + lc.y * ( po.y - pp.y );
  41.   
  42.   cos2phi = scalar * scalar / 
  43.     ( ( lc.x * lc.x + lc.y * lc.y ) * 
  44.       ( ( po.x - pp.x ) * ( po.x - pp.x ) + 
  45.     ( po.y - pp.y ) * ( po.y - pp.y ) ) );
  46.   *pan = sqrt( 1 - cos2phi );
  47.   if( lc.x * ( po.y - pp.y ) - lc.y * (po.x - pp.x) > 0 )
  48.     *pan = - *pan;
  49.  
  50.   dist2 = ( po.x - pp.x ) * ( po.x - pp.x ) +
  51.     ( po.y - pp.y ) * ( po.y - pp.y );
  52.  
  53. #define VOLSCALE_BASE 1000
  54.   *vol = 
  55.     (dist2 > VOLSCALE_BASE * game->settings->game_speed) ? 
  56.     (VOLSCALE_BASE * game->settings->game_speed / dist2) : (1.0);
  57.   *shift = 
  58.     ( USOUND + 
  59.       ( vo.x * ( vp.x - po.x ) + vo.y * ( vp.y - po.y ) ) / sqrt(dist2) ) /
  60.     ( USOUND + 
  61.       ( vp.x * ( vp.x - po.x ) + vp.y * ( vp.y - po.y ) ) / sqrt(dist2) );
  62. }
  63.  
  64. int checkFormat() {
  65.   /*
  66.   if(format != AUDIO_S16SYS) {
  67.     fprintf(stderr, "can't perform fx, unknown format\n");
  68.     return 1;
  69.   }
  70.   */
  71.   return 0;
  72. }
  73.           
  74. void fxShift(float shift, Uint8 *target, Uint8 *source, int len, int *consumed) {
  75.   int i, j, k;
  76.   float l;
  77.   float pa = 0;
  78.  
  79.   if(checkFormat()) {
  80.     *consumed = 0;
  81.     return;
  82.   }
  83.  
  84.   len /= 4; 
  85.  
  86.   for(i = 0; i < len; i++) { // LR pairs 
  87.     for(j = 0; j < 2; j++) { // channels
  88.       pa = i * shift;
  89.       k = (int) pa;
  90.       l = pa - k;
  91.  
  92.       *(Sint16*) (target + 2 * j + 4 * i) +=
  93.     ( *(Sint16*) (source + 2 * j + 4 * (k + 0) ) * ( 1 - l ) +
  94.       *(Sint16*) (source + 2 * j + 4 * (k + 2) ) * ( l ) );
  95.       
  96.     }
  97.   }
  98.   *consumed = ( (int)(len * shift + 0.49999) ) * 4;
  99. }
  100.  
  101. void fxPan(float pan, float vol, Uint8 *buf, int len) {
  102.   int i;
  103.  
  104.   float left_vol =  - vol * ( -1.0 + pan ) / 2.0;
  105.   float right_vol = vol * ( 1.0 + pan ) / 2.0;
  106.  
  107.   if(checkFormat())
  108.     return;
  109.  
  110.   for(i = 0; i < len; i += 4) {
  111.     *(Sint16*) (buf + i) *= left_vol;
  112.     *(Sint16*) (buf + i + 2) *= right_vol;
  113.   }
  114. }
  115.       
  116. static int *sourceBuf = NULL;
  117.  
  118. extern Mix_Chunk *game_fx;
  119.   
  120. void moveSoundSource(int type, int player, int object, int len) {
  121.   Mix_Chunk *chunk;
  122.  
  123.   switch(type) {
  124.   case SOUND_ENGINE:
  125.     chunk = game_fx + SOUND_ENGINE;
  126.     break;
  127.   default:
  128.     fprintf(stderr, "unknown sound source requested\n");
  129.     return;
  130.     break;
  131.   }
  132.   sourceBuf[ player * MAX_PLAYERS + object] =
  133.     ( sourceBuf[ player * MAX_PLAYERS + object ] + len ) % chunk->alen;
  134. }
  135.  
  136. static Uint8 soundBuffer[65536];
  137. static int sourceBuffer[MAX_PLAYERS * MAX_PLAYERS];
  138.  
  139. Uint8* getSoundSource(int type, int player, int object, int len, int *delivered) {
  140.   Mix_Chunk *chunk;
  141.   Uint8* buf;
  142.   int i, rest, pos;
  143.   int loop;
  144.  
  145.   if(sourceBuf == NULL) {
  146.     sourceBuf = sourceBuffer;
  147.     for(i = 0; i < MAX_PLAYERS * MAX_PLAYERS; i++) {
  148.       sourceBuf[ i ] = 0;
  149.     }
  150.   }
  151.  
  152.   switch(type) {
  153.   case SOUND_ENGINE:
  154.     chunk = game_fx + SOUND_ENGINE;
  155.     loop = 1;
  156.     break;
  157.   case SOUND_CRASH:
  158.     chunk = game_fx + SOUND_CRASH;
  159.     loop = 0;
  160.     break;
  161.   default:
  162.     // fprintf(stderr, "unknown sound source requested\n");
  163.     return NULL;
  164.     break;
  165.   }
  166.   
  167.   buf = soundBuffer;
  168.   pos = sourceBuf[ player * MAX_PLAYERS + object ];
  169.  
  170.   rest = chunk->alen - pos;
  171.   if(rest < len) {
  172.     if(loop == 1) {
  173.       memcpy(buf, chunk->abuf + pos, rest);
  174.       memcpy(buf + rest, chunk->abuf, len - rest);
  175.       *delivered = len;
  176.     } else {
  177.       memcpy(buf, chunk->abuf + pos, rest);
  178.       *delivered = rest;
  179.     } 
  180.   } else {
  181.     memcpy(buf, chunk->abuf + pos, len);
  182.     *delivered = len;
  183.   }
  184.   return buf;
  185. }
  186.  
  187.  
  188. #define SOUND_VOL_THRESHOLD 0.01
  189.  
  190. void playCrashSound(int player_i, int player_o) {
  191.   float pan, vol, shift;
  192.   if(game->settings->playEffects == 0)
  193.     return;
  194.   getSound3dData(player_i, player_o, &pan, &vol, &shift);
  195.   printf("starting crash sound with volume %.2f\n",  game->settings->fxVolume * (0.5 + vol / 2.0));
  196.   playGameFX(SOUND_CRASH, game->settings->fxVolume * (0.5 + vol / 2.0));
  197. }
  198.  
  199. void mixEngineSound(int player_i, Uint8* buf, int len) {
  200.     float pan, vol, shift;
  201.     Uint8 *source;
  202.     int clen;
  203.     int consumed;
  204.     int delivered;
  205.     int i;
  206.   
  207.     if(game->settings->playEffects == 0)
  208.       return;
  209.  
  210.     
  211.     for(i = 0; i < game->players; i++) {
  212.       if(i != player_i && game->player[i].data->speed > 0) {
  213.     getSound3dData(player_i, i, &pan, &vol, &shift);
  214.     
  215.     clen = (int)((len / 4) * shift + 1) * 4;
  216.     /*
  217.       printf("sound data for player %d / %d: %.2f %.2f %.2f\n",
  218.       player_i, i, pan, vol, shift);
  219.     */
  220.     if(vol > SOUND_VOL_THRESHOLD) {
  221.       source = getSoundSource(SOUND_ENGINE, player_i, i, clen, &delivered);
  222.       fxPan(pan, game->settings->fxVolume * vol, source, clen);
  223.       fxShift(shift, buf, source, len, &consumed);
  224.       moveSoundSource(SOUND_ENGINE, player_i, i, consumed);
  225.     }
  226.     }
  227.   }
  228. }
  229.